package net.apps123.fragment;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.media.AudioAttributes;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import net.apps123.commonaclasses.MyBaseClass;
import net.apps123.soundmeter.KuoShengMainActivity;
import net.apps123.soundmeter.MyClassKuoSheng;
import net.apps123.soundmeter.R;
import net.apps123.soundmeter.RemoteActivity;
import net.apps123.utils.IpUtils;
import net.apps123.view.SplAdapter;
import net.apps123.view.SplDataBean;
import net.apps123.view.SplView;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executors;

import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.AppSettingsDialog;
import pub.devrel.easypermissions.EasyPermissions;


/**
 * A simple {@link Fragment} subclass.
 * Use the {@link ShengNeng8Fragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class ShengNeng8Fragment extends Fragment implements EasyPermissions.PermissionCallbacks,
        EasyPermissions.RationaleCallbacks {
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    HashMap<String, short[]> deviceList = new HashMap<>();


    private static final int PERMISSION_CAMERA = 1000; //权限的请求码唯一即可
    String[] perms = {Manifest.permission.RECORD_AUDIO, Manifest.permission.INTERNET,
            Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission.ACCESS_WIFI_STATE}; //一些权限用逗号隔


    private Context mContext;

    private EditText c80Et;
    //    private EditText gongLvEt, sheJiGongLvEt;
    private Button genBtn;


    //================================
    boolean isRecording = false;
    //音频源 MIC指的是麦克风
    private final int mAudioSource = MediaRecorder.AudioSource.MIC;
    //（MediaRecoder 的采样率通常是8000Hz AAC的通常是44100Hz。 设置采样率为44100，目前为常用的采样率，官方文档表示这个值可以兼容所有的设置）
    private final int SampleRateInHz = 48000; //采样率
    //输入声道
    private final int channelInMono = AudioFormat.CHANNEL_CONFIGURATION_MONO;
    private final int channelOutMono = AudioFormat.CHANNEL_OUT_MONO;
    //指定音频量化位数 ,在AudioFormaat类中指定了以下各种可能的常量。通常我们选择ENCODING_PCM_16BIT和ENCODING_PCM_8BIT PCM代表的是脉冲编码调制，它实际上是原始音频样本。
    //因此可以设置每个样本的分辨率为16位或者8位，16位将占用更多的空间和处理能力,表示的音频也更加接近真实
    private final int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
    //指定缓冲区大小
    private int mBufferSizeInBytes;
    private String filePath;

    private int mWriteMinBufferSize;
    private AudioAttributes mAudioAttributes;
    AudioRecord mAudioRecord;
    private View mainView;

    private List<Short> recordData = new ArrayList<>();

    public ShengNeng8Fragment() {
        // Required empty public constructor
    }

    public static ShengNeng8Fragment newInstance() {
        return new ShengNeng8Fragment();
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment ZuiDaFragment.
     */
    // TODO: Rename and change types and number of parameters
    public static ShengNeng8Fragment newInstance(String param1, String param2) {
        ShengNeng8Fragment fragment = new ShengNeng8Fragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        mainView = inflater.inflate(R.layout.fragment_shengneng8, container, false);
        mContext = getActivity();

        genBtn = mainView.findViewById(R.id.genBtn);
        genBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                playWav(v);

                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        initAudioRecord();
                        record(v);
                    }
                }, 2000);
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            stopRecord();
                            if (mediaPlayer != null) {
                                mediaPlayer.stop();
                                mediaPlayer.release();
                                mediaPlayer = null;
                            }
                        }catch (Exception ex){
                            ex.printStackTrace();
                        }

                        frequencyAnalyse();
                    }
                }, 5000);
            }
        });

        c80Et = mainView.findViewById(R.id.c80Et);

        //获取权限
        doSomethingWithCamera();
        mainView.findViewById(R.id.ResultBtn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                startActivity(new Intent(getActivity(), HunXiangDetailActivity.class));



            }
        });

        //
        initAudioRecord();

        return mainView;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    }



    @Override
    public void onPermissionsGranted(int i, @NonNull List<String> list) {
        Toast.makeText(getActivity(), "应用获得权限成功", Toast.LENGTH_LONG).show();
        String ipStr = IpUtils.getWifiIPAddress(getActivity());
        Log.d("====", "ipStr==" + ipStr);
    }

    @Override
    public void onPermissionsDenied(int i, @NonNull List<String> list) {
        if (EasyPermissions.somePermissionPermanentlyDenied(this, Arrays.asList(perms))) {
            //在权限弹窗中，用户勾选了'不在提示'且拒绝权限的情况触发
            new AppSettingsDialog.Builder(this).build().show(); //调用接口进入该应用的设置页面
        }

    }

    @Override
    public void onRationaleAccepted(int i) {

    }

    @Override
    public void onRationaleDenied(int i) {

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        // 回调结果传递给EasyPermission
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);

    }

    /**
     * 权限请求方法可直接调用
     */
    @AfterPermissionGranted(PERMISSION_CAMERA)
    public void doSomethingWithCamera() {
        if (EasyPermissions.hasPermissions(getActivity(), perms)) {
            //当前有权限时进行的操作

            String ipStr = IpUtils.getWifiIPAddress(getActivity());
            Log.d("====", "ipStr==" + ipStr);

        } else {
            //没有权限去申请权限
            EasyPermissions.requestPermissions(
                    this, "该权限仅是实现音频分析，请通过权限否则不能使用某些功能！", PERMISSION_CAMERA, perms);
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == AppSettingsDialog.DEFAULT_SETTINGS_REQ_CODE) {
            Toast.makeText(getActivity(), "音频权限为" + EasyPermissions.hasPermissions(getActivity(),
                    perms), Toast.LENGTH_LONG).show();
        }
    }


    private MediaPlayer mediaPlayer;

    private void playWav(View view) {
        try {
            if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                mediaPlayer.stop();

            }
            mediaPlayer = new MediaPlayer();
            mediaPlayer.reset();

            mediaPlayer.setDataSource(getActivity().getBaseContext(), Uri.parse("android.resource://"
                    + getActivity().getBaseContext().getPackageName() + "/" + R.raw.whie_noise_10s_48k));
            mediaPlayer.prepare();
            mediaPlayer.start();
            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    if (mediaPlayer != null) {
                        mediaPlayer.stop();
                        mediaPlayer.release();
                        mediaPlayer = null;
                    }
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        if (mAudioRecord != null) {
            mAudioRecord.release();
            mAudioRecord = null;
        }

        if (mediaPlayer != null) {
            mediaPlayer.stop();
            mediaPlayer.release();
        }


    }

    @Override
    public void onStart() {
        super.onStart();
        if (KuoShengMainActivity.getMqttClient() != null) {
            KuoShengMainActivity.getMqttClient().setCallback(new MqttCallback() {
                @Override
                public void connectionLost(Throwable throwable) {
                    Log.d("=====", "====connectionLost");
                    Toast.makeText(mContext, "===connectionLost==", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
                    Log.d("=====", "====messageArrived");
                    String mqttContent = new String(mqttMessage.getPayload());
//                    Log.d("====", mqttContent.length() + "====" + mqttContent);
//                    Log.d("==cmdStr==" + s, "====" + mqttContent);
                    if (!s.equals("setApp")) {
                        return;
                    }
                    String cmdStr = mqttContent.substring(0, 4);


                }

                @Override
                public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
                    Log.d("=====", "=====deliveryComplete");
                }
            });
        }
    }


    private void initAudioRecord() {
        filePath = getActivity().getExternalFilesDir("Music").getPath() + "/test.pcm";
        mBufferSizeInBytes = AudioRecord.getMinBufferSize(SampleRateInHz, channelInMono, mAudioFormat);
        mAudioRecord = new AudioRecord(mAudioSource, SampleRateInHz, channelInMono, mAudioFormat, mBufferSizeInBytes);

        AudioFormat audioFormat = new AudioFormat.Builder().setSampleRate(SampleRateInHz).setEncoding(mAudioFormat).setChannelMask(channelOutMono).build();
        mAudioAttributes = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();
        File recordFile = new File(filePath);
        if (!recordFile.exists()) {
            try {
                recordFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else{
            recordFile.delete();
        }

    }

    public void record(View view) {
        isRecording = !isRecording;
        String text = isRecording ? "结束" : "录制";
        ((Button) view).setText(text);
        if (isRecording) {
            final File recordFile = new File(filePath);
            if (recordFile.exists()) {
                recordFile.delete();
                try {
                    recordFile.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            mAudioRecord.startRecording();
            Executors.newSingleThreadExecutor().execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        FileOutputStream fileOutputStream = new FileOutputStream(recordFile);
                        byte[] buffer = new byte[mBufferSizeInBytes];
                        while (isRecording) {
                            int read = mAudioRecord.read(buffer, 0, mBufferSizeInBytes);
                            StringBuffer sb = new StringBuffer();
                            if (AudioRecord.ERROR_INVALID_OPERATION != read) {
                                fileOutputStream.write(buffer);

                                short[] shortValue = new short[buffer.length / 2];

                                for (int i = 0; i < shortValue.length; i++) {
                                    shortValue[i] = (short) ((buffer[i * 2] & 0xff) | ((buffer[i * 2 + 1] & 0xff) << 8));
                                    sb.append(shortValue[i] + "," );
                                }
                            }
                            Log.d("====", "==read==" + read + "===" + sb.toString());

                        }
                        fileOutputStream.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    //对录音文件进行分析
    private void frequencyAnalyse() {
        try {
            File tmpFile = new File(filePath);
            if (!tmpFile.exists()) {
                return;
            }
            DataInputStream inputStream = new DataInputStream(new FileInputStream(filePath));

            //16bit采样，因此用short[]
            //如果是8bit采样，这里直接用byte[]
            //从文件中读出一段数据，这里长度是SAMPLE_RATE，也就是1s采样的数据
            short[] buffer = new short[48000];
            for (int i = 0; i < buffer.length; i++) {
                buffer[i] = inputStream.readShort();
            }
            //分析忽略数据48000 * 0.01 = 480
            int AnalNum = 48000 - 480;
            short[] data = new short[AnalNum];

            //为了数据稳定，在这里FFT分析只取最后的FFT_N个数据
            System.arraycopy(buffer, buffer.length - AnalNum,
                    data, 0, AnalNum);

            //前80ms数据
            int numBefore80 = (int) (48000 * 0.080);
            int numAfter1000 = data.length - numBefore80;
            double tmpTotal = 0;
            for (int i = 0; i < numBefore80; i++) {
                tmpTotal = +data[i] * data[i];
            }
            double avgBefore80 = Math.sqrt(tmpTotal / numBefore80);


            //后1000ms数据
            tmpTotal = 0;
            for (int i = numBefore80; i < data.length; i++) {
                tmpTotal = +data[i] * data[i];
            }
            double avgAfter1000 = Math.sqrt(tmpTotal / numAfter1000);

            //求c80
            double c80 = 10 * Math.log(avgBefore80 / avgAfter1000);

            c80Et.setText(c80 + "");


        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     *
     */
    private void stopRecord() {
        if (mAudioRecord != null) {
            genBtn.setText("发声");
            if (mAudioRecord.getState() == AudioRecord.RECORDSTATE_RECORDING) {
                mAudioRecord.stop();
            }
            mAudioRecord.release();
            isRecording = false;
        }
    }
}
